/*
 * @Author: your name
 * @Date: 2021-08-13 09:56:18
 * @LastEditTime: 2021-08-27 15:29:17
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /readbmp/readbitmap.h
 */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include<stdint.h>
#define oops(m) {perror(m); exit(1);}
#define BIT_HEADER_SIZE 14
#define BMP_HEADER_SIZE_SIZE 4
#define IMAGE_HEIGHT  1080
#define IMAGE_WIDTH   1920
/*#define X1 453
#define Y1 211
#define X2 650
#define Y2 342*/

//取Area区域用于区域测试，该区域内包含35个32x32宏块
#define X1Area 427
#define Y1Area 183
#define X2Area 650
#define Y2Area 342
#define DXArea X2Area-X1Area+1
#define DYArea Y2Area-Y1Area+1
#define X1 588//619//542
#define Y1 311//311//263
#define X2 619//650//573
#define Y2 342

#define DX X2-X1+1
#define DY Y2-Y1+1
#define block32 32
#define AreaBlockCount 35
//假设QP为23时候进行量化，则Qstep为9
#define Qstep 9
//Y分量需要17个4x4存储
#define Y_Space 17
//UV分量需要8个4x4存储
#define UV_Space 8

typedef struct bmpInfo {
    uint8_t type;
    int img_width;
    int img_height;
    uint8_t * rgbData;
} BmpInfo;

typedef struct Link_t{
    int ** block;//宏块数据
    int ** dctblock;//宏块dct结果
    int frameNum;//帧号
    int blockNum;//块号
    int blockMedian;//块内Y分量中位数
    int * features;//特征，特征1为dct直流分量，特征2为Z字型扫描前6位加和结果
    struct Link_t * next;//指针域，指向直接后继元素
}link;


BmpInfo * readBmp(char * path);

void readBmpHeader(FILE * bmpfile);
void readBmpInfoHeader(FILE * bmpfile);
uint8_t * getRgbData(FILE * bmpfile);
uint8_t * getRgbaData(FILE * bmpfile);
void write_mat(FILE *fp, uint8_t *m, uint32_t size);
void partialButterfly32(const int* src, int* dst, int shift, int line);
int ** dct32_c(int** src);
void getFullChooseArea16x16(char* path, int *yuv_yAreaBlockData, int *yuv_uvAreaBlockData, int x1, int y1, int x2, int y2);
void getBlockPosition(int** arr, int x1, int y1, int x2, int y2);
uint8_t * getBlockRgbaData(uint8_t * data, int** blockPosition, int*** rgbdata, int row_count);
void getYuvfromRgb(int ***rgbdata, int ***yuvdata, int dx, int dy);
void putYinBlock(int **yuv_yData, int ***yuvData, int dx, int dy);
